#ifndef __SV2_STREAMER__
#define __SV2_STREAMER__

#include "sms_core.h"
#include <string>
#include <chrono>
#include <mutex>
#include <queue>
#include <condition_variable>
#include "rtspSend.hpp"

namespace sv2
{

  class VideoStreamer;
  class ImgMsg {
    public:
      ImgMsg(cv::Mat img_, nlohmann::json msg_) : img(img_), msg(msg_) {}
      cv::Mat img;
      nlohmann::json msg;
  };

  class StreamerCppNode_Rknn : public sms::BaseNode
  {
  public:
    StreamerCppNode_Rknn(
        std::string job_name,
        std::string param_file,
        std::string ip = "127.0.0.1",
        int port = 9094,
        nlohmann::json kwargs = {}
        ): sms::BaseNode("StreamerCppNode_Rknn", job_name, param_file, ip, port, kwargs)
    {
      // 读取节点参数
      this->_image_topic = this->get_param("image_topic", "/live/sensor/image_raw");
      this->_image_width = this->get_param("width", 640);
      this->_image_height = this->get_param("height", 480);
      this->_port = this->get_param("port", "8554");
      this->_rtsp_url = this->get_param("rtsp_url", "/live");
      this->_use_h265 = this->get_param("use_h265", false);
      this->_bitrate = this->get_param("bitrate", 2);
      this->_fps = this->get_param("fps", 30);
      this->params_help();

      /*
      logger.info("--job_name: " + job_name);
      logger.info("--param_file: " + param_file);
      logger.info("image_topic: " + this->_image_topic);
      logger.info("image_width: " + std::to_string(static_cast<int>(this->_image_width)));
      logger.info("image_height: " + std::to_string(static_cast<int>(this->_image_height)));
      logger.info("port: " + this->_port);
      logger.info("rtsp_url: rtsp://127.0.0.1:" + this->_port + this->_rtsp_url);
      logger.info("use_h265: " + std::to_string(static_cast<bool>(this->_use_h265)));
      logger.info("bitrate: " + std::to_string(static_cast<int>(this->_bitrate)));
      */

      sms::msleep(1000);
      // 初始化 推流分辨率(640, 480)，端口号8554，比特率1Mb
      bool ret1 = this->_vs.setup(this->_rtsp_url, cv::Size(this->_image_width, this->_image_height), this->_use_h265, this->_port, this->_bitrate, this->_fps); // 2Mb
      if (ret1)
        std::cout << "Setup is OK" << std::endl;
      else
        std::cout << "Setup is Bad" << std::endl;

      int i = 0;
      while (i < 10)
      {
        bool ret2 = this->_vs.isOpened();
        if (ret2)
            std::cout << "RTSP channel is Opened" << std::endl;
        else
            std::cout << "RTSP channel is Closed" << std::endl;
        if (ret2)
          break;
        else
        {
          i++;
          sms::msleep(2000);
        }
      }
      _det_res_sub = new sms::Subscriber(this->_image_topic, "std_msgs::Null", std::bind(&StreamerCppNode_Rknn::full_res_callback, this, std::placeholders::_1)); //new need
    }
    ~StreamerCppNode_Rknn()
    {
    }
    void run();

    void full_res_callback(nlohmann::json msg)
    {
      cv::Mat img = sms::sms2cvimg(msg);
      // std::cout << "get " << img.cols << ", " << img.rows << std::endl;
      ImgMsg imgmsg(img, msg);
      // 放入到阻塞队列中
      {
        std::lock_guard<std::mutex> lock(this->_full_queue_mtx);
        this->_full_queue.push(imgmsg);
      }
      // 通知主线程取数据
      this->_full_cv.notify_one();
    }
    std::string _image_topic;
    int _image_width;
    int _image_height;
    std::string _port;
    std::string _rtsp_url;
    int _bitrate;
    bool _use_h265;
    float _fps;

    YourStreamer _vs;
  private:
    // 订阅话题
    sms::Subscriber* _det_res_sub;

    std::mutex _full_queue_mtx;
    std::queue<ImgMsg> _full_queue;
    std::condition_variable _full_cv;
};

}
#endif
